package app.core.thread;

import app.core.enums.MessageType;
import app.core.model.impl.Message;
import app.core.model.impl.User;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import static app.core.model.IMessage.*;

/**
 * @author Guo.Yang
 * @version 1.0
 * @date 2023/1/15 15:46
 */
public class ServiceRunnable extends MyRunnable {
    private InputStream inputStream;
    private OutputStream outputStream;
    private User user;


    public ServiceRunnable(Socket socket){
        this.user = new User(socket, "用户" + System.currentTimeMillis());
        this.inputStream = getInput(socket);
        this.outputStream = getOutput(socket);
    }

    /**
     * 更新登录列表
     */
    public void changeList(){
        Message ok = new Message();
        ArrayList<String> list = new ArrayList<>();
        //第0个元素放置当前连接用户
        list.add(user.getSocket().toString());
        list.add(user.getName());
        //从1开始放置当前登录列表
        for(User user : sockets.values()){
            list.add(user.getSocket().toString());
            list.add(user.getName());
        }
        ok.setMessages(list);
        try {
            all(ok, MessageType.LINK);
        } catch (IOException e) {
            System.out.println("连接失败!");
        }
    }

    /**
     * 接受消息
     */
    public void accept(){
        while (user.getSocket().isConnected()){
            byte[] bytes = new byte[BYTES_MAX_SIZE];
            try {
                int read = inputStream.read(bytes, 0, BYTES_MAX_SIZE);
                if (read > 0){
                    String data = new String(bytes, 0, read, CHAR_SET);
                    List<Message> messages = Message.create(data);
                    messages.forEach(message -> {
                        try {
                            DealMessage(message);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                }
            } catch (IOException e) {
                System.out.println("[Service]连接出现异常:"+ e.getMessage());
                break;
            }catch (Exception un){
                System.out.println("未知异常:"+ un.getMessage());
            }
        }
    }

    @Override
    public void run() {
        if (this.inputStream != null && this.outputStream != null){
            sockets.put(user.getSocket().toString(),user);
            changeList();
            accept();
            //连接关闭
            synchronized ("") {
                sockets.remove(user.getSocket().toString());
                changeList();
            }
        }
    }

    public  int  changeName(Message message) throws IOException {
        String name = message.getData(NAME);
        if(name !=null && !user.getName().equals(name)){
            for(User u:sockets.values()){
                if(u.getName().equals(name)){
                    Message msg = Message.getInstance("昵称重复!");
                    none(msg);
                    return 0;
                }
                if(name.length()>20){
                    Message msg = Message.getInstance("昵称长度不能超过20!");
                    none(msg);
                    return 0;
                }
            }
            synchronized ("") {
                String old = user.getName();
                user.setName(name);
                changeList();
                Message rename = new Message();
                rename.setData(HEAD, "系统提示");
                rename.setMessage(old + "修改名称为["+name+"]");
                all(rename,MessageType.ALL);
                return 1;
            }
        }
        return 2;
    }

    public void DealMessage(Message message) throws Exception{
        int state = changeName(message);
        if (state == 0){
            return;
        }

        MessageType messageType = MessageType.valueOf(message.getData(TYPE));
        switch (messageType){
            case ORDINARY:
                ordinary(message);
                break;
            case ALL:
                all(message);
                break;
            case FAIL:
                fail(message);
                break;
            case NONE:
            default:
                Message msg = new Message();
                msg.setMessage("错误的请求!");
                none(msg);
        }
    }

    public void ordinary(Message message) throws IOException {
        String who = message.getData("who");
        User sendTo = sockets.get(who);
        Socket socket = sendTo.getSocket();
        if (socket == null){
            Message msg = new Message();
            msg.setMessage("用户不在线!");
            none(message);
            return;
        }
        message.setData(HEAD, "你 发送给 "+ sendTo.getName());
        send(message, this.user.getSocket(),MessageType.ORDINARY);
        message.setData(HEAD, this.user.getName()+" 发送给 你");
        send(message, socket, MessageType.ORDINARY);
    }

    public void all(Message message) throws IOException {
        message.setData(HEAD, user.getName()+" 发送给 所有人");
        all(message,MessageType.ALL);
    }

    public void all(Message message, MessageType type) throws IOException {
        for (User u : sockets.values()){
            send(message, u.getSocket(), type);
        }
    }

    public void fail(Message message){
        System.out.println("客户端错误:"+ message.getMessage());
    }

    public void none(Message message) throws IOException {
        send(message,user.getSocket(),MessageType.FAIL);
    }

    public void send(Message message, Socket socket, MessageType type) throws IOException {
        synchronized ("") {
            OutputStream output = getOutput(socket);
            message.setData(TYPE, type.name());
            output.write(message.toString().getBytes(CHAR_SET));
            output.flush();
        }
    }


}
